
package com.jf.cloud.coupon.util;

import cn.hutool.core.collection.CollectionUtil;
import com.jf.cloud.api.coupon.constant.CouponProdType;
import com.jf.cloud.api.coupon.constant.CouponType;
import com.jf.cloud.common.order.vo.CouponOrderVO;
import com.jf.cloud.common.order.vo.ShopCartItemVO;
import com.jf.cloud.common.util.PriceUtil;

import java.util.*;

/**
 * 协助优惠券进行选择
 * @author zz
 */
public class ChooseCouponHelper {
    /**
     * 购物项
     */
    private final List<ShopCartItemVO> shopCartItems;
    /**
     * 含有的优惠券列表
     */
    private final List<CouponOrderVO> shopCoupons;
    /**
     * 选中的优惠券id
     */
    private final List<Long> couponIds;

    /**
     * 用户是否选中优惠券
     */
    private final Integer userChangeCoupon;
    /**
     * 选中的优惠券
     */
    private CouponOrderVO chooseCoupon;

    /**
     * 可用优惠券的商品实际金额（商品实际金额 - 商品分摊金额）
     */
    private Long prodCanUseCouponActualTotal;

    /**
     * 优惠金额
     */
    private Long couponReduce;

    /**
     * 优惠金额
     */
    private Long chooseCouponProdAmount;

    /**
     * 优惠券在订单中的优惠金额
     */
    private Long couponInOrderAmount;


    /**
     * 优惠金额关联店铺map
     */
    private final Map<Long,Long> shopReduceMap = new HashMap<>(12);

    public ChooseCouponHelper(List<ShopCartItemVO> shopCartItems, List<CouponOrderVO> shopCoupons, List<Long> couponIds, Integer userChangeCoupon) {
        this.shopCartItems = shopCartItems;
        this.shopCoupons = shopCoupons;
        this.couponIds = couponIds;
        this.userChangeCoupon = userChangeCoupon;
    }

    public CouponOrderVO getChooseCoupon() {
        return chooseCoupon;
    }


    public Long getCouponReduce() {
        return this.couponReduce;
    }

    public Map<Long, Long> getShopReduceMap() {
        return shopReduceMap;
    }

    public ChooseCouponHelper invoke() {
        // 没有平台优惠券直接返回
        if(CollectionUtil.isEmpty(shopCartItems)){
            return this;
        }


        // 用户选中的关于该店铺的优惠券，一家店只能选择一张优惠券
        chooseCoupon = null;

        // 可用优惠券的商品实际金额（商品实际金额 - 商品分摊金额）
        prodCanUseCouponActualTotal = 0L;
        Date now = new Date();
        for (CouponOrderVO shopCoupon : shopCoupons) {
            if (shopCoupon.getStartTime().getTime() > now.getTime() || shopCoupon.getEndTime().getTime() < now.getTime()) {
                continue;
            }
            // 该优惠券关联的商品id
            List<Long> prodIds = shopCoupon.getSpuIds();
            // 可用优惠券的商品实际金额（商品实际金额 - 商品分摊金额）
            prodCanUseCouponActualTotal = 0L;
            for (ShopCartItemVO shopCartItem : shopCartItems) {
                // 套餐不参与优惠券活动
                if (Objects.nonNull(shopCartItem.getComboId()) && shopCartItem.getComboId() != 0) {
                    continue;
                }
                shopCartItem.setIsShareReduce(0);
                // 该商品是否在该优惠券可用
                boolean isCouponsProd = isCouponsProd(shopCartItem.getSpuId(), prodIds, shopCoupon.getSuitableProdType());
                if (isCouponsProd) {
                    shopCartItem.setIsShareReduce(1);
                    prodCanUseCouponActualTotal = prodCanUseCouponActualTotal + shopCartItem.getActualTotal();
                }
            }
            Date date = new Date();
            // 如果该商品实际总金额大于等于优惠券最低使用金额，并且开始时间大于优惠券的使用时间，则优惠券可用
            if (prodCanUseCouponActualTotal >= shopCoupon.getCashCondition()  && shopCoupon.getStartTime().getTime() < date.getTime()) {
                // 将优惠券标记为可用状态
                shopCoupon.setCanUse(true);
                // 聚合 用户选中的关于该店铺的优惠券
                if (CollectionUtil.isNotEmpty(couponIds)) {
                    for (Long couponId : couponIds) {
                        if (Objects.equals(couponId, shopCoupon.getCouponId())) {
                            chooseCoupon = shopCoupon;
                            chooseCouponProdAmount = prodCanUseCouponActualTotal;
                            break;
                        }
                    }
                }
                // 如果用户没有选择优惠券，系统默认选择一张可用优惠券
                if (chooseCoupon == null && !Objects.equals(userChangeCoupon, 1)) {
                    chooseCoupon = shopCoupon;
                    chooseCouponProdAmount = prodCanUseCouponActualTotal;
                }
            }
        }
        for (CouponOrderVO shopCoupon : shopCoupons) {
            // 该优惠券关联的商品id
            List<Long> prodIds = shopCoupon.getSpuIds();
            if(Objects.nonNull(chooseCoupon) && !Objects.equals(shopCoupon.getCouponUserId(),chooseCoupon.getCouponUserId())){
                continue;
            }
            for (ShopCartItemVO shopCartItem : shopCartItems) {
                shopCartItem.setIsShareReduce(0);
                // 该商品是否在该优惠券可用
                boolean isCouponsProd = isCouponsProd(shopCartItem.getSpuId(), prodIds, shopCoupon.getSuitableProdType());
                if (isCouponsProd) {
                    shopCartItem.setIsShareReduce(1);
                }
            }
        }
        prodCanUseCouponActualTotal = chooseCouponProdAmount;
        if (chooseCoupon != null) {
            chooseCoupon.setChoose(true);
            // 计算优惠券优惠金额
            calculateCouponReduce();
            // 设置分摊优惠金额
            setShareReduce();
        }
        return this;
    }

    /**
     * 判断某个商品是否在此优惠券中
     *
     * @param prodId         在该店铺中的商品商品id
     * @param couponProdIds  优惠券关联的商品id
     * @param couponProdType 优惠券适用商品类型
     * @return 商品是否在此优惠券中
     */
    private boolean isCouponsProd(Long prodId, List<Long> couponProdIds, Integer couponProdType) {

        if (CouponProdType.ALL.value().equals(couponProdType)) {
            return true;
        }
        if (CouponProdType.PROD_IN.value().equals(couponProdType)) {
            if (CollectionUtil.isEmpty(couponProdIds)) {
                return false;
            }
            for (Long couponProdId : couponProdIds) {
                if (Objects.equals(couponProdId, prodId)) {
                    return true;
                }
            }
            return false;
        }
        return false;
    }


    /**
     * 计算优惠金额
     */
    private void calculateCouponReduce() {
        couponReduce = 0L;
        couponInOrderAmount = 0L;
        // 代金券
        if (CouponType.C2M.value().equals(chooseCoupon.getCouponType())) {
            couponInOrderAmount = chooseCoupon.getReduceAmount();
        }
        // 折扣券
        if (CouponType.C2D.value().equals(chooseCoupon.getCouponType())) {
            couponInOrderAmount = prodCanUseCouponActualTotal - PriceUtil.divideByBankerRounding((long) (prodCanUseCouponActualTotal * chooseCoupon.getCouponDiscount()), 10);
            chooseCoupon.setReduceAmount(couponInOrderAmount);
        }
        couponReduce = couponReduce + couponInOrderAmount;
    }

    /**
     * 设置分摊优惠金额
     */
    private void setShareReduce() {
        long sumReduce = 0L;
        // 用于方便计算的金额，因为在计算比例时会进行了乘以100操作，所有这里除以100
        for (int i = 0; i < shopCartItems.size(); i++) {
            ShopCartItemVO shopCartItem = shopCartItems.get(i);
            long shareReduce;
            if (shopCartItem.getIsShareReduce() == 1) {
                // couponInOrderAmount这个不做整除100的操作是因为会丢失精度，在这里把最后乘100的操作去除就好了
                shareReduce = PriceUtil.divideByBankerRoundingThan(couponInOrderAmount * shopCartItem.getActualTotal(), prodCanUseCouponActualTotal, false);
            } else {
                shareReduce = 0L;
            }
            // 分摊的优惠金额 不能大于商品金额
            long minShareReduce = Math.min(shareReduce, shopCartItem.getTotalAmount());
            //如果是最后一项，直接将剩余的优惠金额赋值给他
            if(i + 1 == shopCartItems.size()) {
                minShareReduce =  Math.min(couponReduce - sumReduce,shopCartItem.getTotalAmount());
            }
            if (Objects.equals(chooseCoupon.getShopId(), 0L)) {
                // 平台分摊的每一个购物项优惠金额
                shopCartItem.setPlatformShareReduce(shopCartItem.getPlatformShareReduce() + minShareReduce);
                shopCartItem.setPlatformCouponAmount(minShareReduce);
            } else {
                // 商家分摊的每一个购物项优惠金额
                shopCartItem.setShareReduce(shopCartItem.getShareReduce() + minShareReduce);
                shopCartItem.setShopCouponAmount(minShareReduce);
            }
            shopCartItem.setActualTotal(shopCartItem.getActualTotal() - minShareReduce);
            sumReduce = minShareReduce + sumReduce;

            // 将对应店铺优惠券优惠的金额放入map中
            if(shopReduceMap.containsKey(shopCartItem.getShopId())) {
                Long shopReduce = shopReduceMap.get(shopCartItem.getShopId());
                shopReduceMap.put(shopCartItem.getShopId(), shopReduce + minShareReduce);
            }else{
                shopReduceMap.put(shopCartItem.getShopId(),minShareReduce);
            }
        }

        // 满减重新赋值
        couponReduce = sumReduce;
    }
}
